package com.syh.bishe.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.syh.bishe.Util.RedisConstants;
import com.syh.bishe.pojo.*;
import com.syh.bishe.mapper.TransactionsMapper;
import com.syh.bishe.service.IBillService;
import com.syh.bishe.service.ICarbonCreditsService;
import com.syh.bishe.service.ILogService;
import com.syh.bishe.service.ITransactionsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author syh
 * @since 2024-07-02
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class TransactionsServiceImpl extends ServiceImpl<TransactionsMapper, Transactions> implements ITransactionsService {
    private final RedissonClient redissonClient;
    private final ExecutorService executor;
    private final TransactionsMapper transactionsMapper;
    private final ICarbonCreditsService carbonCreditsService;
    private final IBillService billService;
    private final StringRedisTemplate stringRedisTemplate;
    private final ILogService logService;

    @Override
    public List<Transactions> getTransactions(Integer sellerId) {
        List<Transactions> transactions = transactionsMapper.getTransactions(sellerId);
        return transactions;
    }

    @Override
    public BigDecimal getById_transactions(Integer id) {
        BigDecimal creditAmount = transactionsMapper.getById_transactions(id);
        return creditAmount;
    }

    @Override
    public List<Transactions> getTransactionsByBuyerId(Integer buyerId) {
        try {
            List<Transactions> transactions = transactionsMapper.getTransactionsByBuyerId(buyerId);
            return transactions;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<Transactions> getTransactionsBySellerId(Integer sellerId) {
        try {
            List<Transactions> transactions = transactionsMapper.getTransactionsBySellerId(sellerId);
            return transactions;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<Transactions> getTransactionsBySellerId_a(Integer sellerId) {
        try {
            List<Transactions> transactions = transactionsMapper.getTransactionsBySellerId_a(sellerId);
            return transactions;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<Transactions> getTransactionsByBuyerId_a(Integer buyerId) {
        try {
            List<Transactions> transactions = transactionsMapper.getTransactionsByBuyerId_a(buyerId);
            return transactions;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<Transactions> getList() {
        try {
            List<Transactions> transactions = transactionsMapper.getList();
            return transactions;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public List<Transactions> getLists() {
        try {
            List<Transactions> transactions = transactionsMapper.getLists();
            return transactions;
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public DataIndex getTMR(Integer buyerId) {
        List<BigDecimal> tmr = transactionsMapper.getTMR(buyerId);
        if(tmr.size()==0||tmr.size()==1){
            return new DataIndex("碳买入", tmr.size()==0? BigDecimal.valueOf(0.0) :tmr.get(0), BigDecimal.valueOf(0));
        }
        if (tmr.get(1).compareTo(BigDecimal.ZERO) == 0) {
            return new DataIndex("碳买入", tmr.get(0), BigDecimal.valueOf(0));
        }
        BigDecimal difference = tmr.get(0).subtract(tmr.get(1));
        return new DataIndex("碳买入", tmr.get(0), difference.divide(tmr.get(1), 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));
    }
    @Override
    public DataIndex getTMRvalue(Integer buyerId) {
        List<BigDecimal> tmr = transactionsMapper.getTMRvalue(buyerId);
        if(tmr.size()==0||tmr.size()==1){
            return new DataIndex("碳买入的支出", tmr.size()==0? BigDecimal.valueOf(0.0) :tmr.get(0), BigDecimal.valueOf(0));
        }
        if (tmr.get(1).compareTo(BigDecimal.ZERO) == 0) {
            return new DataIndex("碳买入的支出", tmr.get(0), BigDecimal.valueOf(0));
        }
        BigDecimal difference = tmr.get(0).subtract(tmr.get(1));
        return new DataIndex("碳买入的支出", tmr.get(0), difference.divide(tmr.get(1), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));
    }
    @Override
    public DataIndex getTMCvalue(Integer sellerId) {
        List<BigDecimal> tmr = transactionsMapper.getTMCvalue(sellerId);
        if(tmr.size()==0||tmr.size()==1){
            return new DataIndex("碳卖出的收入", tmr.size()==0? BigDecimal.valueOf(0.0) :tmr.get(0), BigDecimal.valueOf(0));
        }
        if (tmr.get(1).compareTo(BigDecimal.ZERO) == 0) {
            return new DataIndex("碳卖出的收入", tmr.get(0), BigDecimal.valueOf(0));
        }
        BigDecimal difference = tmr.get(0).subtract(tmr.get(1));
        return new DataIndex("碳卖出的收入", tmr.get(0), difference.divide(tmr.get(1), 4, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100)));
    }

    @Override
    public List<Transactions> getTransactionSell(Integer sellerId) {
        try {
            List<Transactions> transactions = transactionsMapper.getTransactionSell(sellerId);
            return transactions;
        }catch (Exception e){
            return null;
        }
    }
    @Override
    public List<Transactions> getTransactionBuy(Integer buyerId) {
        try {
            List<Transactions> transactions = transactionsMapper.getTransactionBuy(buyerId);
            return transactions;
        }catch (Exception e){
            return null;
        }
    }

    @Override
    public List<Notifications> getNotification(Integer id) {
        List<Notifications> notifications = new ArrayList<>();
        List<Transactions> sell=transactionsMapper.getTransactionSell(id);
        for (Transactions transactions : sell) {
            if(transactions.getStatus().equals("已提交")){
                notifications.add(new Notifications("有客户请求购买",
                        "客户请求购买您发布的交易"+transactions.getId()+"均价为"+transactions.getFinalAvg()+"，请前往查看",
                        "mdi mdi-cart-outline",
                        "success", "/tj/mac"));
            }else if(transactions.getStatus().equals("竞拍中")){
                notifications.add(new Notifications("交易竞拍中",
                        "您发布的交易"+transactions.getId()+"目前最高价"+transactions.getFinalAvg()+"，请前往查看",
                        "mdi mdi-cart-outline",
                        "warning", "/tj/mac"));
            }else continue;
        }
        List<Transactions> buy=transactionsMapper.getTransactionBuy(id);
        for (Transactions transactions : buy) {
            if(transactions.getStatus().equals("卖家已确认")){
                notifications.add(new Notifications("请前往确认交易并付款",
                        "您购买的交易"+transactions.getId()+"卖家已确认，请前往查看",
                        "mdi mdi-message-text-outline",
                        "success", "/tj/mar"));
            }else if(transactions.getStatus().equals("卖家结束竞拍")){
                notifications.add(new Notifications("竞拍成功，请前往付款",
                        "您竞拍的交易"+transactions.getId()+"卖家已结束竞拍，最终价格为"+transactions.getFinalAvg()+"，请前往查看",
                        "mdi mdi-message-text-outline",
                        "warning", "/tj/mar"));
            }
        }
        return notifications;
    }

    @Override
    public List<Transactions> getAllMainSome(Integer id) {
        List<Transactions> res = new ArrayList<>();
        String s = stringRedisTemplate.opsForValue().get(RedisConstants.MAIN_TJY_DATA + id);
        if(StrUtil.isNotBlank(s)){
            res = JSONUtil.toList(s, Transactions.class);
            return res.stream().limit(8).collect(Collectors.toList());
        }
        List<Transactions> transactions = transactionsMapper.getTransactionSell(id);
        for (Transactions transaction : transactions) {
            transaction.setStatus("卖出碳额度");
            res.add(transaction);
        }
        List<Transactions> transactions1 = transactionsMapper.getTransactionBuy(id);
        for (Transactions transactions2 : transactions1) {
            transactions2.setStatus("买入碳额度");
            res.add(transactions2);
        }
        res.sort(Comparator.comparing(Transactions::getTransactionDate).reversed());
        stringRedisTemplate.opsForValue().set(RedisConstants.MAIN_TJY_DATA + id, JSONUtil.toJsonStr(res), RedisConstants.CACHE_TJY_TTL, TimeUnit.SECONDS);
        return res.stream().limit(8).collect(Collectors.toList());
    }

    @Override
    @Transactional //事务回滚
    public Result add(Transactions transactions) {
        transactions.setFinalSum(transactions.getCreditAmount().multiply(transactions.getFinalAvg()));
        transactions.setStatus("已发布");
        if (save(transactions)) {
            carbonCreditsService.updateCreditAmount(transactions.getSellerId(), transactions.getCreditAmount());
            logService.save(new Log().setInfo("公司"+transactions.getSellerId()+"发布交易,类型"+transactions.getType()+"，" +
                            ""+ transactions.getId()+"出售碳额度"+transactions.getCreditAmount()+"吨，" +
                            "单价"+transactions.getFinalAvg()+"元/吨，总价"+transactions.getFinalSum()+"元")
                    .setDate(LocalDateTime.now())
                    .setUserId(transactions.getSellerId()));
            return Result.success();
        } else {
            return Result.error("发布失败");
        }
    }

    @Override
    public Result purchase(Transactions transactions) {
        transactions.setFinalSum(transactions.getCreditAmount().multiply(transactions.getFinalAvg()));
        transactions.setTransactionDate(LocalDateTime.now());
        if (updateById(transactions)) {
            //carbonCreditsMapper.updateCreditAmountAdd(transactions.getBuyerId(), transactions.getCreditAmount());
            logService.save(new Log().setInfo("公司" + transactions.getBuyerId() + "购买-" + transactions.getType() +
                            "：" + transactions.getId() + "购买碳额度" + transactions.getCreditAmount() + "吨，" +
                            "单价" + transactions.getFinalAvg() + "元/吨，总价" + transactions.getFinalSum() + "元，提交订单等待卖家确认")
                    .setDate(LocalDateTime.now())
                    .setUserId(transactions.getBuyerId()));
            return Result.success();
        } else {
            return Result.error("购买失败");
        }
    }

    @Override
    public Result placeBid(Transactions transactions) {
        try {
            // 提交任务到线程池，并等待结果
            return executor.submit(() -> {
                RLock lock = redissonClient.getLock("auction-lock:" + transactions.getId());
                try {
                    boolean isLocked = lock.tryLock(10, 30, TimeUnit.SECONDS);
                    if (!isLocked) {
                        return Result.error("竞拍失败，请稍后再试");
                    }

                    // 检查当前出价是否高于现有最高价
                    if (getById_transactions(transactions.getId()).compareTo(transactions.getFinalAvg()) >= 0) {
                        return Result.error("出价失败,价格小于或等于现在的最高价");
                    }

                    // 计算总价并设置交易时间
                    transactions.setFinalSum(transactions.getCreditAmount().multiply(transactions.getFinalAvg()));
                    transactions.setTransactionDate(LocalDateTime.now());

                    // 更新交易记录
                    if (updateById(transactions)) {
                        // 记录日志信息
                        logService.save(new Log().setInfo("公司" + transactions.getBuyerId() + "出价竞拍-" + transactions.getType() +
                                        "：" + transactions.getId() + "购买碳额度" + transactions.getCreditAmount() + "吨，" +
                                        "单价" + transactions.getFinalAvg() + "元/吨，总价" + transactions.getFinalSum() + "元，提交订单等待卖家结束竞拍")
                                .setDate(LocalDateTime.now())
                                .setUserId(transactions.getBuyerId()));

                        return Result.success();
                    } else {
                        return Result.error("竞拍失败");
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return Result.error("出现异常");
                } finally {
                    // 确保释放锁
                    if (lock.isHeldByCurrentThread()) {
                        lock.unlock();
                    }
                }
            }).get(); // 获取线程任务的执行结果

        } catch (InterruptedException | ExecutionException e) {
            Thread.currentThread().interrupt();
            return Result.error("竞拍处理出现异常");
        }
    }

    @Override
    public Result confirmTransaction_m3(Transactions transactions) {
        if (transactions.getFinalSum().compareTo(carbonCreditsService.getAccount(transactions.getBuyerId())) > 0) {
            return Result.error("当前余额不足，无法完成购买请先充值");
        }
        transactions.setTransactionDate(LocalDateTime.now());
        transactions.setStatus("买家已确认");
        if (updateById(transactions)) {
            carbonCreditsService.updateAccount_s(transactions);
            carbonCreditsService.updateAccount_a(transactions);
            carbonCreditsService.updateCreditAmountAdd(transactions.getBuyerId(), transactions.getCreditAmount());
            billService.addBill_success(transactions);
            logService.save(new Log().setInfo("公司" + transactions.getBuyerId() + "确认购买-" + transactions.getType() +
                            "：" + transactions.getId() + "购买碳额度" + transactions.getCreditAmount() + "吨，" +
                            "单价" + transactions.getFinalAvg() + "元/吨，总价" + transactions.getFinalSum() + "元，确认订单，已付款")
                    .setDate(LocalDateTime.now())
                    .setUserId(transactions.getBuyerId()));
            return Result.success();
        } else {
            return Result.error("确认失败");
        }
    }

    @Override
    public Result confirmTransaction_m4(Transactions transactions) {
        transactions.setStatus("卖家已确认");
        if (updateById(transactions)) {
            logService.save(new Log().setInfo("公司" + transactions.getSellerId() + "确认交易-" + transactions.getType() +
                            "：" + transactions.getId() + "卖出碳额度" + transactions.getCreditAmount() + "吨，" +
                            "单价" + transactions.getFinalAvg() + "元/吨，总价" + transactions.getFinalSum() + "元，确认订单，等待买家付款")
                    .setDate(LocalDateTime.now())
                    .setUserId(transactions.getSellerId()));
            return Result.success();
        } else {
            return Result.error("确认失败");
        }
    }

    @Override
    public Result confirmTransaction_a_m4(Transactions transactions) {
        transactions.setStatus("卖家结束竞拍");
        transactions.setTransactionDate(LocalDateTime.now());
        if (updateById(transactions)) {
            logService.save(new Log().setInfo("公司" + transactions.getSellerId() + "确认交易-" + transactions.getType() +
                            "：" + transactions.getId() + "卖出碳额度" + transactions.getCreditAmount() + "吨，" +
                            "单价" + transactions.getFinalAvg() + "元/吨，总价" + transactions.getFinalSum() + "元，确认订单，等待买家付款")
                    .setDate(LocalDateTime.now())
                    .setUserId(transactions.getSellerId()));
            return Result.success();
        } else {
            return Result.error("结束竞拍失败");
        }
    }

    @Override
    public Result confirmTransaction_admin(Transactions transactions) {
        if (transactions.getStatus().equals("审核通过")) {
            transactions.setStatus("已审核");
        }
        if (transactions.getStatus().equals("驳回")) {
            carbonCreditsService.updateCreditAmountAdd(transactions.getSellerId(), transactions.getCreditAmount());
        }
        if (updateById(transactions)) {
            logService.save(new Log().setInfo("审核员审核" + transactions.getId() + "公司" + transactions.getSellerId()
                            + "卖出碳额度" + transactions.getCreditAmount() + "吨，" +
                            "总价" + transactions.getFinalSum() + "元，审核结果：" +
                            "" + transactions.getStatus())
                    .setDate(LocalDateTime.now()).setUserId(transactions.getSellerId())
            );
            return Result.success();
        } else {
            return Result.error("确认失败");
        }
    }

    @Override
    public Result confirmTransaction_admin_a(Transactions transactions) {
        if (transactions.getStatus().equals("驳回")) {
            carbonCreditsService.updateAccount_add_buy(transactions);
            carbonCreditsService.updateAccount_add_sell(transactions);
            carbonCreditsService.updateCreditAmountAdd(transactions.getSellerId(), transactions.getCreditAmount());
            carbonCreditsService.updateCreditAmount(transactions.getBuyerId(), transactions.getCreditAmount());
            billService.addBill_cansel(transactions);
        }
        if (transactions.getStatus().equals("驳回") || transactions.getStatus().equals("审核通过")) {
            if (updateById(transactions)) {
                logService.save(new Log().setInfo("审核员审核" + transactions.getId() + "公司" + transactions.getSellerId()
                                + "卖出碳额度" + transactions.getCreditAmount() + "吨，" +
                                "买入公司" + transactions.getBuyerId() + "，总价" + transactions.getFinalSum() + "元，审核结果：" +
                                "" + transactions.getStatus())
                        .setDate(LocalDateTime.now())
                        .setUserId(transactions.getBuyerId()));
                return Result.success();
            } else {
                return Result.error("确认失败");
            }
        } else {
            return Result.error("请正确填写审核结果");
        }
    }

}
